﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace LiveSequence.Common.Graphics
{
  public class ClipboardHelper
  {
    /// <summary>
    /// Places the element on clipboard.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <returns></returns>
    public static bool PlaceElementOnClipboard(UIElement element)
    {
      bool success = true;
      System.Drawing.Bitmap gdiBitmap = null;
      MemoryStream metafileStream = null;

      RenderTargetBitmap wpfBitmap = MakeRenderTargetBitmap(element);
      try
      {
        gdiBitmap = MakeSystemDrawingBitmap(wpfBitmap);
        metafileStream = MakeMetafileStream(gdiBitmap);

        DataObject dataObj = new DataObject();
        dataObj.SetData(DataFormats.Bitmap, gdiBitmap);
        dataObj.SetData(DataFormats.EnhancedMetafile, metafileStream);
        Clipboard.SetDataObject(dataObj, true);
      }
      catch
      { success = false; }
      finally
      {
        if (gdiBitmap != null)
        { gdiBitmap.Dispose(); }
        if (metafileStream != null)
        { metafileStream.Dispose(); }
      }

      return success;
    }
    /// <summary>
    /// Makes the render target bitmap.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <returns></returns>
    private static RenderTargetBitmap MakeRenderTargetBitmap(UIElement element)
    {
      element.Measure(new System.Windows.Size(double.PositiveInfinity,
        double.PositiveInfinity));
      element.Arrange(new Rect(new System.Windows.Point(0, 0),
        element.DesiredSize));
      // added more quality to the rendered imagen
      double dFactor = 3.5D;
      RenderTargetBitmap rtb = new RenderTargetBitmap(
        (int)Math.Ceiling(element.DesiredSize.Width * dFactor),
        (int)Math.Ceiling(element.DesiredSize.Height * dFactor),
        96 * dFactor,
        96 * dFactor, 
        PixelFormats.Pbgra32);
      rtb.Render(element);
      return rtb;
    }

    /// <summary>
    /// Makes the system drawing bitmap.
    /// </summary>
    /// <param name="wpfBitmap">The WPF bitmap.</param>
    /// <returns></returns>
    private static System.Drawing.Bitmap MakeSystemDrawingBitmap(RenderTargetBitmap wpfBitmap)
    {
      BitmapEncoder encoder = new TiffBitmapEncoder();
      encoder.Frames.Add(BitmapFrame.Create(wpfBitmap));
      MemoryStream stream = new MemoryStream();
      encoder.Save(stream);

      System.Drawing.Bitmap gdiBitmap = new System.Drawing.Bitmap(stream);
      stream.Close();
      stream.Dispose();

      return gdiBitmap;
    }

    /// <summary>
    /// Makes the metafile stream.
    /// </summary>
    /// <param name="image">The image.</param>
    /// <returns></returns>
    private static MemoryStream MakeMetafileStream(Bitmap image)
    {
      System.Drawing.Graphics graphics = null;
      Metafile metafile = null;
      MemoryStream stream = new MemoryStream();
      try
      {
        using (graphics = System.Drawing.Graphics.FromImage(image))
        {
          IntPtr hdc = graphics.GetHdc();
          metafile = new Metafile(stream, hdc);
          graphics.ReleaseHdc(hdc);
        }
        using (graphics = System.Drawing.Graphics.FromImage(metafile))
        { graphics.DrawImage(image, 0, 0); }
      }
      finally
      {
        if (graphics != null)
        { graphics.Dispose(); }
        if (metafile != null)
        { metafile.Dispose(); }
      }
      return stream;
    }

  }
}
